//
//  RSAUtil.swift
//  8btc
//
//  Created by Felix Yuan on 2019/11/4.
//  Copyright © 2019 Hangzhou Shichuo Information Technology Co, Ltd. All rights reserved.
//

import Foundation
import Security
import OpenSSL

public struct RSAUtil {
    // MARK: 通过公私钥字符串生成公私钥

    // 通过公钥生成key
    public static func DecryptWith(encryptContent: String, publicKey: String) -> Data? {
        guard let encodeData = Data(base64Encoded: encryptContent) else {
            return nil
        }

        let publicKeyString = formatPublicKey(publicKey)
        let chPublicKey = publicKeyString.bytes
        let publicKeyData = Data(bytes: chPublicKey, count: chPublicKey.count)
        let bytes = publicKeyData.bytes
        let bio = BIO_new_mem_buf(bytes, Int32(bytes.count))

        guard let publicRSA = PEM_read_bio_RSA_PUBKEY(bio, nil, nil, nil) else {
            BIO_free(bio)
            return nil
        }
        BIO_free(bio)

        let rsa_len = Int(RSA_size(publicRSA))
        var p_en = [UInt8](repeating: 0, count: rsa_len)

        var c_data = encodeData.map { $0 }
        let lent = RSA_public_decrypt(Int32(rsa_len), &c_data, &p_en, publicRSA, RSA_PKCS1_PADDING)
        if lent < 0 {
            print("解密失败")
            return nil
        }

        let result = Data(p_en.filter { $0 > 0 })
        return result
    }

    private static func formatPublicKey(_ string: String) -> String {
        var publicKeyString = string
        // 为了避免写法的不同意，如果公钥已经带有下面标记字符，先去除，后面再统一加上固定格式
        publicKeyString = publicKeyString.replacingOccurrences(of: "-----BEGIN PUBLIC KEY-----", with: "")
        publicKeyString = publicKeyString.replacingOccurrences(of: "-----END PUBLIC KEY-----", with: "")
        publicKeyString = publicKeyString.replacingOccurrences(of: "-", with: "")
        publicKeyString = publicKeyString.replacingOccurrences(of: "\r", with: "")
        publicKeyString = publicKeyString.replacingOccurrences(of: "\n", with: "")
        publicKeyString = publicKeyString.replacingOccurrences(of: "\t", with: "")
        publicKeyString = publicKeyString.replacingOccurrences(of: " ", with: "")

        // 从内存中读取,公钥字符串开头要加上“-----BEGIN PUBLIC KEY-----\n”，结尾加上“\n-----END PUBLIC KEY-----\n”。否则会出现error:0906D06C:PEM routines:PEM_read_bio:no start line
        return "-----BEGIN PUBLIC KEY-----\n\(publicKeyString)\n-----END PUBLIC KEY-----\n"
    }
}
